#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <errno.h>
#include <linux/input.h>
#include<stdlib.h>
#include <pthread.h>

/*
在屏幕上实现刮刮乐效果
1、输出上面一层图片或者颜色
2、获取触屏的时候所在点的像素坐标
3、把图片上对应的像素左边输出在触屏点（也就是覆盖原来的）
4、可以使用多线程，主线程在一值获取坐标。另外一个线程就在输出图片
*/

int fd_lcd;//fd文件描述符
int *map_lcd; //mapped映射
int fd_ts;//touch screen触摸屏
int x,y;

int lcd_init()
{
	//打开LCD的设备文件
	fd_lcd = open("/dev/fb0",O_RDWR);
	if(-1 == fd_lcd)
	{
		perror("open LCD failed:");
		return -1;
	}
	
	//映射LCD
    //成功的时候返回申请映射空间的地址
	map_lcd = (int *)mmap(	NULL,//申请映射空间的指定地址，一般可填NULL，表示由系统自动分配
							800*480*4,//申请的映射空间的大小，单位字节
							PROT_READ|PROT_WRITE,//映射空间的属性，读写属性
							MAP_SHARED,//映射空间的属性，是否共享
							fd_lcd,//目标文件的文件描述符
							0);//映射空间的地址偏移量表示，0不偏移
	if(map_lcd == MAP_FAILED)
	{
		perror("map LCD failed:");
		return -1;
	}
}

int lcd_uinit()
{
	//解除映射
	munmap(map_lcd,800*480*4);
	//关闭LCD的设备文件
	close(fd_lcd);
}

//输出要被刮出的图片
int lcd_draw_bmp()
{
	//打开图片文件
	int fd_bmp;
	fd_bmp = open("24bit.bmp",O_RDWR);//图片也是800*400
	if(-1 == fd_bmp)
	{
		perror("open bmp failed:");
		return -1;
	}
	
	//读取图片文件里的颜色数据，这里图片的尺寸也是800*400
	char buf_bmp[800*480*3];//因为图片是24bit
	
	//原因是图片文件除了颜色数据之外，还有54字节的图片格式、属性数据，
	//且这54字节的数据处于文件头
	lseek(fd_bmp,54,SEEK_SET);
	read(fd_bmp,buf_bmp,sizeof(buf_bmp));
	
	//关闭图片文件
	close(fd_bmp);
	
	//对读取的bmp的颜色数据进行ARGB整合
	int buf_lcd[800*480];
	int i;
	
	for(i=0;i<800*480;i++)
	{
		// ARGB			A		R			G		B
		int la = 0x00<<24;
		int lb = buf_bmp[i*3+2]<<16; //B
		int lc = buf_bmp[i*3+1]<<8;  //G
		int ld = buf_bmp[i*3];       //R
		buf_lcd[i] =la|lb|lc|ld;
		
	}

    //因为在图片上最后一行的数据在bmp中就是第一行
    *(map_lcd+y*800+x) = buf_lcd[(480-y)*800+x];				
			
}

//初始化图片为白色
int lcd_draw_bmp1(){
    int i,j;
    for(i=0;i<480;i++){
        for(j=0;j<799;j++){
            *(map_lcd+j*800+i) = 0x00FFFFFF;//前面两位00表示图片的透明度
        }
    }
}

//根据xy来输出图片
int lcd_draw_bmp2(){
    //以触摸点为中心，画正方形，扩大画图的像素；要注意数组越界问题
    int i,j;
    for(j=y-20;j<=y+20;j++){
        for(i=x-20;i<=x+20;i++)
        {
          lcd_draw_bmp();            
        }            
    }
    		
}


int ts_init(){
    //打开触摸屏的设备文件	
	fd_ts = open("/dev/input/event0",O_RDWR);
	if(-1 == fd_ts)
	{
		perror("open ts failed :");
		return -1;
	}
    
}

//获取触摸屏的像素坐标
int ts_xy(){
    struct input_event ts;
	
	while(1)
	{
		//读取触摸屏的设备文件
		read(fd_ts,&ts,sizeof(ts));		//阻塞函数
		printf("type=%d,code=%d,value=%d\n",ts.type,ts.code,ts.value);
		
		if(ts.type==EV_ABS && ts.code==ABS_X)
		{
			//x = ts.value;			//蓝色
            //因为板子的尺寸是1024*600，所以需要等比例缩放。
			x = ts.value*800/1024;	//黑色
		}
		
		if(ts.type==EV_ABS && ts.code==ABS_Y)
		{
			//y = ts.value;			//蓝色
			y = ts.value*480/600;	//黑色
		}
		
		if(ts.type==EV_ABS && ts.code==ABS_PRESSURE && ts.value==0)
		{
			break;
		}
		else if(ts.type==EV_KEY && ts.code==BTN_TOUCH && ts.value==0)
		{
			break;
		}
	}
	
	printf("(%d,%d)\n",x,y);

}
	
void *func()
{
	do{
          usleep(500);
         lcd_draw_bmp2();
    }while(!(x>=750 && y<=50));
    return ;
}
int main()
{
    
	lcd_init();
	//1.bmp分辨率是511*311
	lcd_draw_bmp(0,0,"./1.bmp");
    ts_init();
  
	pthread_t pid;
	pthread_create(&pid,NULL,func,NULL);
	do{
        ts_xy();
    }while(!(x>=750 && y<=50));
	
	close(fd_ts);
	lcd_uinit();
	
	return 0;
}


